package com.itany.nmms.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itany.nmms.constant.DictConstant;
import com.itany.nmms.dao.ProductMapper;
import com.itany.nmms.dao.SequenceMapper;
import com.itany.nmms.entity.Product;
import com.itany.nmms.entity.ProductExample;
import com.itany.nmms.entity.Sequence;
import com.itany.nmms.entity.SequenceExample;
import com.itany.nmms.exception.FileUploadErrorException;
import com.itany.nmms.exception.ProductExistException;
import com.itany.nmms.exception.RequestParameterErrorException;
import com.itany.nmms.service.ProductService;
import com.itany.nmms.util.ParameterUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author 石小俊
 * @date 2024年04月24日 18:12
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ProductServiceImpl implements ProductService {

    @Autowired(required = false)
    private ProductMapper productMapper;
    @Autowired(required = false)
    private SequenceMapper sequenceMapper;

    @Override
    public void addProduct(String name, String price, String description, MultipartFile file, String typeId) throws RequestParameterErrorException, ProductExistException, FileUploadErrorException {
        if (ParameterUtil.isNull(name) || ParameterUtil.isNull(price) || ParameterUtil.isNull(description) || ParameterUtil.isNull(typeId)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        // 此时的图片有且仅有一张
        // 取出对应的文件,判断是否是空文件
        if (file.isEmpty()) {
            throw new RequestParameterErrorException("上传的商品图片不能为空");
        }

        // 同一种类型的商品名称不能重复
        ProductExample example = new ProductExample();
        example.or()
                .andNameEqualTo(name)
                .andProductTypeIdEqualTo(Integer.parseInt(typeId));
        List<Product> products = productMapper.selectByExample(example);
        if (!products.isEmpty()) {
            throw new ProductExistException("该类型的商品已经存在了");
        }

        // 开始添加
        // 准备一个商品对象,为对应的属性赋值
        Product product = new Product();
        product.setName(name);
        product.setPrice(Double.parseDouble(price));
        product.setDescription(description);
        product.setProductTypeId(Integer.parseInt(typeId));

        // 生成商品编号
        // 商品编号由三部分组成:标志位(设置常量)、日期(当前年月日)、序列号(数字位)
        // 对于序列号,将其存储到对应的序列号表sys_sequence中
        // 要求:对于同一种类型的编号在数据库中有且仅有一条数据
        // 只要取出这一条数据,就能直到当前序列号到多少了
        // 在生成序列号的时候,存在两种场景
        // 1.尚未使用过序列号(第一次使用)
        // 创建一条初始数据,保存到数据库
        // 将初始数据添加到数据库中
        // 2.已经使用过序列号
        // 判断当前序列号的值是否达到了最大值
        // 如果达到了最大值,则下一个值为初始值
        // 如果尚未达到最大值,则下一个值在原有序列号的值的基础上+1
        // 修改序列号表中的数据

        // 根据标志位查询对应的序列号的值
        SequenceExample sequenceExample = new SequenceExample();
        sequenceExample.or()
                .andNameEqualTo(DictConstant.PRODUCT_NO_PREFIX);
        List<Sequence> sequences = sequenceMapper.selectByExample(sequenceExample);
        if (sequences.isEmpty()) {
            // 如果没有查询到数据,说明尚未使用过序列号
            // 创建一条初始数据,保存到数据库
            Sequence sequence = new Sequence();
            sequence.setName(DictConstant.PRODUCT_NO_PREFIX);
            sequence.setValue(DictConstant.PRODUCT_NO_INIT_VALUE);
            // 将初始数据添加到数据库中
            sequenceMapper.insertSelective(sequence);
            // 生成对应的商品编号
            product.setProductNo(DictConstant.PRODUCT_NO_PREFIX + new SimpleDateFormat("yyyyMMdd").format(new Date()) + sequence.getValue());
        } else {
            // 如果查询到数据了,则此时查询的数据一定是有且仅有一条
            // 取出这一条数据
            Sequence sequence = sequences.get(0);
            // 判断当前序列号的值是否达到了最大值
            if (DictConstant.PRODUCT_NO_MAX_VALUE.equals(sequence.getValue())) {
                // 如果达到了最大值,则下一个值为初始值
                sequence.setValue(DictConstant.PRODUCT_NO_INIT_VALUE);
            } else {
                // 如果尚未达到最大值,则下一个值在原有序列号的值的基础上+1
                sequence.setValue(ParameterUtil.nextValue(sequence.getValue()));
            }
            // 修改序列号表中的数据
            sequenceMapper.updateByPrimaryKeySelective(sequence);
            // 生成对应的商品编号
            product.setProductNo(DictConstant.PRODUCT_NO_PREFIX + new SimpleDateFormat("yyyyMMdd").format(new Date()) + sequence.getValue());
        }



        try {
            // 上传商品图片
            // 在服务器根目录中创建一个专门用于存储所有图片的父目录
            // 每天在父目录中创建一个以当天年月日命名的子目录,用于存储当天的所有图片
            String path = DictConstant.PRODUCT_IMAGE_ROOT_FOLDER + new SimpleDateFormat("yyyyMMdd").format(new Date());
            // 获取服务器地址
//        String cp = session.getServletContext().getRealPath(path);
            String cp = ResourceUtils.getURL("classpath:").getPath()+path;
            File f = new File(cp);
            f.mkdirs();
            System.out.println("********************cp:"+cp);

            // 为上传的图片增加一个毫秒值的后缀
            String fileName = file.getOriginalFilename();
            fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "-" + new Date().getTime() + fileName.substring(fileName.lastIndexOf("."));

            // 设置商品图片属性值
            product.setImage(path + File.separator + fileName);

            // 添加商品
            productMapper.insertSelective(product);
            // 上传图片
            file.transferTo(new File(cp, fileName));

        } catch (Exception e) {
            e.printStackTrace();
            throw new FileUploadErrorException("上传商品图片失败");
        }

    }

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    @Override
    public PageInfo<Product> findPage(String pageNo, String pageSize) {
        if (ParameterUtil.isNull(pageNo)) {
            pageNo = DictConstant.PRODUCT_DEFAULT_PAGE_NO;
        }
        if (ParameterUtil.isNull(pageSize)) {
            pageSize = DictConstant.PRODUCT_DEFAULT_PAGE_SIZE;
        }
        PageHelper.startPage(Integer.parseInt(pageNo), Integer.parseInt(pageSize));

        List<Product> products = productMapper.selectAll();

        PageInfo<Product> productPage = new PageInfo<>(products);

        // 当当前页不是第一页,且该页没有数据的时候
        if (!"1".equals(pageNo) && productPage.getList().isEmpty()) {
            // 进入到上一页
            int page = Integer.parseInt(pageNo) - 1;
            productPage = findPage(page + "", pageSize);
        }

        return productPage;
    }

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    @Override
    public Product findById(String id) throws RequestParameterErrorException {
        if (ParameterUtil.isNull(id)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        Product product = productMapper.selectByPrimaryKey(Integer.parseInt(id));
        return product;
    }

    @Override
    public void modifyProduct(String id, String name, String price, String description, MultipartFile file, String typeId) throws RequestParameterErrorException, ProductExistException, FileUploadErrorException {
        if (ParameterUtil.isNull(id) || ParameterUtil.isNull(name) || ParameterUtil.isNull(price) || ParameterUtil.isNull(description) || ParameterUtil.isNull(typeId)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        ProductExample example = new ProductExample();
        example.or()
                .andNameEqualTo(name)
                .andProductTypeIdEqualTo(Integer.parseInt(typeId))
                .andProductIdNotEqualTo(Integer.parseInt(id));
        List<Product> products = productMapper.selectByExample(example);
        if (!products.isEmpty()) {
            throw new ProductExistException("该类型的商品已经存在了");
        }
        // 准备修改
        // 准备一个商品对象,为对应的属性赋值
        Product product = new Product();
        product.setProductId(Integer.parseInt(id));
        product.setName(name);
        product.setPrice(Double.parseDouble(price));
        product.setDescription(description);
        product.setProductTypeId(Integer.parseInt(typeId));
        if (!file.isEmpty()) {
            try {
                String path = DictConstant.PRODUCT_IMAGE_ROOT_FOLDER + new SimpleDateFormat("yyyyMMdd").format(new Date());
                // 获取服务器地址
//                String cp = session.getServletContext().getRealPath(path);
                String cp = ResourceUtils.getURL("classpath:").getPath()+path;
                System.out.println("********************cp:"+cp);
                File f = new File(cp);
                f.mkdirs();

                // 为上传的图片增加一个毫秒值的后缀
                String fileName = file.getOriginalFilename();
                fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "-" + new Date().getTime() + fileName.substring(fileName.lastIndexOf("."));

                // 设置商品图片属性值
                product.setImage(path + File.separator + fileName);

                // 修改商品信息
                productMapper.updateByPrimaryKeySelective(product);
                // 上传图片
                file.transferTo(new File(cp, fileName));

            } catch (Exception e) {
                e.printStackTrace();
                throw new FileUploadErrorException("上传商品图片失败");
            }
        } else {
            productMapper.updateByPrimaryKeySelective(product);
        }
    }


    @Override
    public void removeById(String id) throws RequestParameterErrorException {
        if (ParameterUtil.isNull(id)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        productMapper.deleteByPrimaryKey(Integer.parseInt(id));
    }
}
